import React, {memo, useEffect, useRef, useState} from 'react';
import {useDispatch, useSelector} from "react-redux";
import "./calculation.css";
import CalculateTable from "../../../../../components/calculateTable/CalculateTable";
import Title from "../../../../../components/Title/Title";
import {calCqMean, calQuantityMean, deepClone, getAnalysisInfo, getContextPath} from "../../../../../common/utils";
import {MENU_STYLE, WELLS_COLUMN, WELLS_ROW} from "../../../plate/config";
import {BASELINE_CORRECTION, BASELINE_SUBTRACTED_CURVE_FIT, DATA_ANALYSIS_METHOD, DATA_ANALYSIS_METHOD_1, DATA_ANALYSIS_METHOD_2, DATA_ANALYSIS_METHOD_3, RAW_DATA} from "./config";
import {EntityType, FluorescenceCanvas, FluorescenceEntity} from "../../../../../common/canvas";
import {saveAllThreshold, saveBaseLine, saveBaselineType, saveChannel, saveCqSingleThreshold, saveDataAnalysisMethod, saveHeatMapInfo, saveTargetSelectedArr} from "./store/actionCreators";
import {saveAnalysisShowLineArr} from "../../../plate/store/actionCreators";
import {CQMAN, CUSTOM_THRESHOLD, EXTREMUM, REGRESSION, SINGLE_THRESHOLD, THRESHOLD} from "../../../store/constants";
import {saveData} from "../../../store/actionCreators";
import {Dropdown, Menu, message} from "antd";
import {AMPLIFICATION} from "../../../protocol/config";
import request from "../../../../../services/request";
import {useDebounce} from "../../../../../common/myHooks";
import {saveEndPointSetting} from "../../../analysis/components/endPoint/store/actionCreators";

/*
仅校准实验用，校准bug修改以zhaoqiang/Calibration/coefficientCorrection分支为准
*/

export default memo(function Calculation() {
  const dispatch = useDispatch();
  const {
    data,
    cqSingleThreshold,
    baselineType,
    heatMapInfo,
    pcrAllCycle,
    baseLine,
    allThreshold,
    analysisShowLineArr,
    targetSelectedArr,
    dataAnalysisMethod,
    isCN,
    channels,
    lineOption,
    isLoadDone
  } = useSelector(
    state => ({
      data: state.dataReducer.data,
      analysisShowLineArr: state.plateReducer.analysisShowLineArr,  //  包含可以画线的well(同时有target和sampleName)
      targetSelectedArr: state.quantificationReducer.targetSelectedArr, //  保存Target Setting中Opt被选中的target的name
      dataAnalysisMethod: state.quantificationReducer.dataAnalysisMethod,  //  分析的方法(3种)
      allThreshold: state.quantificationReducer.allThreshold,  //  所有target的threshold
      pcrAllCycle: state.protocolReducer.pcrAllCycle,
      baseLine: state.quantificationReducer.baseLine,
      heatMapInfo: state.quantificationReducer.heatMapInfo,
      baselineType: state.quantificationReducer.baselineType,
      cqSingleThreshold: state.quantificationReducer.cqSingleThreshold,
      isCN: state.languageReducer.isCN,
      channels: state.calculationReducer.channel,
      lineOption: state.calculationReducer.lineOption,
      isLoadDone: state.calculationReducer.isLoad
    }));
  const [channel, setChannel] = useState(channels);
  const [count, setCount] = useState(0);
  const [click, setClick] = useState(false);
  const [stringChar, setStringChar] = useState([]);
  const [slope, setSlope] = useState([]);
  const [singleHole, setSingleHole] = useState([]);
  const [coefficientArr, setCoefficientArr] = useState(channels.coefficientArr);//channel的精校数据
  const [bigDataCalibration, setBigDataCalibration] = useState(data.coefficients);//更singleHole新至大数据
  const [target, setTarget] = useState([]);  //  target条目
  const [channelArr, setChannelArr] = useState(channels.wellArr);
  const [channelLines, setChannelLines] = useState(channels.leastChannelLines);
  const [isCq, setIsCq] = useState(true); //  切换Cq/Log
  const [showMethodSetting, setShowMethodSetting] = useState(false); //  显示Method Setting
  const [showMoreData, setShowMoreData] = useState(false); //  显示More Data
  const [startX, setStartX] = useState(0);  //  鼠标按下起始位置横坐标
  const [startY, setStartY] = useState(0);  //  鼠标按下起始位置纵坐标
  const [leftDown, setLeftDown] = useState(false);  //  鼠标左键是否按下
  const [lineId, setLineId] = useState(-1);  //  选中的线的ID,选中表格条目也会改变此ID
  const [wellId, setWellId] = useState([]);  //  选中well的target
  const [autoAxes, setAutoAxes] = useState(true);
  const [minY, setMinY] = useState(0);
  const [maxY, setMaxY] = useState(Infinity);
  const [showLargeQuantificationPic, setShowLargeQuantificationPic] = useState(false);
  const [moreDataTableTitle, setMoreDataTableTitle] = useState([]);
  const [moreTableTargetNameList, setMoreTableTargetNameList] = useState([]);
  const [heatMapTarget, setHeatMapTarget] = useState([]);
  const [singleThreshold, setSingleThreshold] = useState(data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD);
  const quantificationBox = useRef();
  const quantificationStyle = {
    paddingLeft: 60,
    paddingTop: 10,
    paddingBottom: 50,
    paddingRight: 10,
    dataPaddingLeft: 10,
    dataPaddingBottom: 10,
    dataPaddingTop: 10,
    dataPaddingRight: 10,
    axisTitleLeft: "RFU(10^3)",
    axisTitleLeftPadding: 30,
    axisTitleBottom: isCN ? "循环数" : "Cycles",
    axisTitleBottomPadding: 20,
    maxX: pcrAllCycle,
    xDataStart: 1
  };
  const dataAnalysisMethods = [DATA_ANALYSIS_METHOD_1, DATA_ANALYSIS_METHOD_2, DATA_ANALYSIS_METHOD_3];
  let cloneTarget = [];
  let cloneChannelArr = [];
  let cloneChannelLines = [];
  let cloneCoefficientArr = [];
  let cloneTargetSelectedArr = [];
  let cloneAnalysisShowLineArr = [];
  let channelLinesDataArray = [];
  let cloneSlopeCopy = [];
  let cloneData = {};
  let cloneSlope = [];

  useEffect(() => {
    setChannelArr(channels.wellArr);
    setChannelLines(channels.leastChannelLines);
    cloneChannelLines = deepClone(channelLines, cloneChannelLines);
    cloneAnalysisShowLineArr = deepClone(analysisShowLineArr, cloneAnalysisShowLineArr);
    // console.log(data);
  }, [data]);

  useEffect(() => {
    //  设置表格信息
    let targetMap = new Map(),
      dataTarget = [];
    data.wells.forEach(item => item.targets.forEach(item_ => targetMap.set(item_.name, {
      ...item_,
      opt: targetSelectedArr.includes(item_.name)
    })));
    targetMap.forEach(value => dataTarget.push(value));
    dataTarget.forEach(item => data.targets.find(it => it.uuid === item.uuid && (item.threshold = it.threshold)));
    setTarget(dataTarget);  //  剔除掉同名的target,保存所有不同名字的target的全部信息
    let cycleNum = 0;
    data.protocol.stages.forEach(item => item.state === AMPLIFICATION && (cycleNum += item.cycle));
    setMoreDataTableTitle(Array(cycleNum).fill(null));
    setMoreTableTargetNameList(["All"].concat(data.targets.map(item => item.name)));
    setHeatMapTarget(data.targets.map(item => item.channel));

    //  设置Data Analysis Method
    let method;
    switch (data.analysisMethodSetting.method) {
      case BASELINE_SUBTRACTED_CURVE_FIT:
        method = DATA_ANALYSIS_METHOD_1;
        break;
      case BASELINE_CORRECTION:
        method = DATA_ANALYSIS_METHOD_2;
        break;
      case RAW_DATA:
        method = DATA_ANALYSIS_METHOD_3;
        break;
      default:
        method = DATA_ANALYSIS_METHOD_1;
    }
    dispatch(saveDataAnalysisMethod(method));
  }, [data]);

  useEffect(() => {
    if (showMoreData) {
      return;
    }
    let quantificationCurve;  //  quantification实例
    data.targets.forEach(target => {
      if (!targetSelectedArr.includes(target.name)) {
        return;
      }
    });
    if (!showLargeQuantificationPic) {
      quantificationCurve = FluorescenceCanvas.init("quantification", quantificationStyle);
      if (!autoAxes) {
        quantificationCurve.setAutoAxisY(false);
        quantificationCurve.setMaxY(maxY);
        quantificationCurve.setMinY(minY);
      }
    } else {
      quantificationCurve = FluorescenceCanvas.init("largeQuantification", quantificationStyle);
    }
    quantificationCurve.setMaxX(pcrAllCycle);
    if (isCq) {
      if (data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD) {
        data.targets.forEach(item => {
          if (!targetSelectedArr.includes(item.name)) {
            return;
          }
          quantificationCurve.addEntity(FluorescenceEntity.getInstance({
            type: EntityType.THRESHOLD,
            id: item.name,
            dataList: [item.threshold],
            color: item.color,
            text: item.threshold
          }));
        });
      }
      analysisShowLineArr.forEach(item => {
        if (item.omit.value === "true" || !data.wells[item.id].show || !targetSelectedArr.includes(item.target.value)) {
          return;
        }
        quantificationCurve.addEntity(FluorescenceEntity.getInstance({
          id: item.id,
          dataList: data.wells[item.id].lines[item.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]],
          color: item.color,
          highlight: item.id === Number(wellId[0]),
          text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
        }));
      });
    } else {
      quantificationCurve.setDrawLogAxis(true);
      quantificationCurve.setAutoAxisY(false);
      if (autoAxes) { //  log图自动坐标轴固定设置
        quantificationCurve.setMinY(-2);
        quantificationCurve.setMaxY(2);
      } else {  //  对输入值进行log
        minY > 0 && quantificationCurve.setMinY(Math.log10(minY));
        maxY > 0 && quantificationCurve.setMaxY(Math.log10(maxY));
      }
      if (data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD) {
        data.targets.forEach(item => {
          if (!targetSelectedArr.includes(item.name)) {
            return;
          }
          let logThreshold = Math.log10(item.threshold);
          if (logThreshold <= 0) {
            logThreshold = 0.01;
          }
          let logDataList = [logThreshold];
          // TODO: 坐标y轴的值是Math.pow(10,logDataList)
          quantificationCurve.addEntity(FluorescenceEntity.getInstance({
            type: EntityType.THRESHOLD,
            id: item.name,
            dataList: logDataList,
            color: item.color,
            text: item.threshold
          }));
        });
      }
      let maxYLog = 0;
      analysisShowLineArr.forEach(item => {
        if (item.omit.value === "true" || !data.wells[item.id].show || !targetSelectedArr.includes(item.target.value)) {
          return;
        }
        let beforeLogData = data.wells[item.id].lines[item.channelIndex][DATA_ANALYSIS_METHOD[dataAnalysisMethod]];
        let logData = [];
        for (let i = beforeLogData.length - 1; i >= 0; i--) {
          if (beforeLogData[i] <= 0.001) {
            logData[logData.length] = -3;
          } else {
            logData.push(Math.log10(beforeLogData[i]));
          }
        }
        logData.reverse();
        logData = logData.filter(item => item !== -Infinity && !isNaN(item)); //  剔除-Infinite和NaN
        maxYLog = Math.max(maxYLog, ...logData);
        quantificationCurve.addEntity(FluorescenceEntity.getInstance({
          id: item.id,
          dataList: logData,
          color: item.color,
          highlight: item.id === Number(wellId[0]),
          text: WELLS_ROW[item.row] + WELLS_COLUMN[item.col]
        }));
      });
    } // Cq&Log的图例
    quantificationCurve.onMousemove(function () {
      this && data.analysisMethodSetting.mode === CUSTOM_THRESHOLD && typeof this.id !== Number && changeThreshold(this);
      this && setLineId(this.id);
    });
    return () => {
      quantificationCurve.destroyCanvas();
    };
  }, [dataAnalysisMethod, pcrAllCycle, data, analysisShowLineArr, targetSelectedArr, isCq, showMoreData, showLargeQuantificationPic, minY, maxY, autoAxes, wellId]);

  useEffect(() => {
    dispatch(saveHeatMapInfo({...heatMapInfo, target: data.targets.map(item => item.channel)[0]}));
  }, []);

  useEffect(() => {
    //拿到所有有数据孔的origin数据；直接计算保存大数据结构里，不用再框选、勾选opt以及calculate
    //数组遍历获取
    cloneData = deepClone(data, cloneData);
    // console.log(data);
    let allChannelData = cloneData.wells.filter(item => item.sampleName !== "");
    // 根据等级数据计算重复的个数,找单个孔是哪一个sampleName
    let obj = {};
    let str = [];
    for (let i = 0; i < allChannelData.length; i++) {
      let item = allChannelData[i].sampleName; // a为计算的属性,可换成b,c
      obj[item] = (obj[item] + 1) || 1;
    }
    var onlyName = [];
    // TODO:多个单一孔？？
    for (let i in obj) {
      if (obj[i] === 1) {
        onlyName.push(i);
      }
      setSingleHole(onlyName);
    }
    // console.log(onlyName);
    // console.log(allChannelData);
    let testArr = [], targetsChannelIndex = [];
    let differ = 0, originIndex = [0, 1, 2, 3, 4, 5];
    let map = new Map([['FAM', 0], ['SYBR', 0], ['EvaGreen', 0],
      ['VIC', 1], ['HEX', 1], ['JOE', 1], ['540', 1], ['560', 1],
      ['TAMRA', 2], ['CY3', 2],
      ['TEXAS RED', 3], ['ROX', 3], ['610', 3], ['TEX615', 3],
      ['CY5', 4], ['Quasar 670', 4], ["Mustang Purple", 4], ['LIZ', 4],
      ['CY5.5', 5], ["Quasar 705", 5]]);
    for (let i = 0; i < allChannelData.length; i++) {
      let hasOriginData = [];
      let name = allChannelData[i].sampleName;
      differ++;
      //待改？？target不全的情况？
      let nullOriginArr = [];
      //well每一项origindata都为零也要排除在外！！
      // let hasOriginData = allChannelData[i].lines.filter(item => item.quantificationOrigin.length !== 0 && (item.quantificationOrigin.reduce((cur, val) => {
      //   return cur + val;
      // })) !== 0);
      let originData = allChannelData[i].lines.filter(item => item.quantificationOrigin);
      //少于等于六个targets的情况,让target数目与origin一致
      // 应把除了target占用的通道以外的origin数据剔除，target=>chennelIndex===origin索引
      allChannelData[i].targets.forEach(item => targetsChannelIndex.push(map.get(item.channel)));//target的索引
      arrChange(originIndex, targetsChannelIndex);
      //剔除origin里不含targets的数据
      for (let j = 0; j < originData.length; j++) {
        // for (let k = 0; k < originIndex.length; k++) {
        //   if (j !== originIndex[k]) {
        //     hasOriginData.push(originData[j]);
        //   }
        // }
        originIndex.indexOf(j) === -1 && hasOriginData.push(originData[j]);
      }
      nullOriginArr = originIndex;
      // allChannelData[i].lines.forEach((item, index) => {
      //   if (item.quantificationOrigin.length === 0 || item.quantificationOrigin.reduce((cur, val) => {
      //     return cur + val;
      //   }) === 0) {
      //     nullOriginArr.push(index);
      //   }
      // });
      //测试
      if (hasOriginData.length !== allChannelData[i].targets.length) {
        console.log("报错！");
        console.log("targets个数与有数据通道不一致！：", hasOriginData, allChannelData[i].targets);
      }
      for (let j = 0; j < hasOriginData.length; j++) {
        let targetIndex = allChannelData[i].targets[j].channelIndex;
        testArr.push({quantificationOrigin: hasOriginData[j].quantificationOrigin, sampleName: name, channelIndex: targetIndex, differ: differ, nullOrigin: nullOriginArr});
      }
    }
    // console.log(testArr);
    let totalChannelData = groupBy(testArr, function (item) {
      return [item.sampleName];
    });
    /*
     数组预处理，把每组well的数据单独存成一个按sampleName分新的三维对象数组
     [【【samplename相同】，【samplename相同】】，【】]
     */
    let partList;
    for (let i = 0; i < totalChannelData.length; i++) {
      for (let j = 0; j < totalChannelData[i].length; j++) {
        partList = groupBy(totalChannelData[i], function (item) {
          return [item.differ];
        });
        totalChannelData[i] = partList;
      }
    }
    //单孔处理
    for (let i = 0; i < totalChannelData.length; i++) {
      //单个孔升维，不加这句会有单孔bug，但一个well若做六次实验是否需重改？？==>判断六次实验的是否是唯一孔的sample
      if (onlyName.length === 1) {
        if (totalChannelData[i][0].length === 6 && totalChannelData[i][0][0].sampleName === onlyName[0]) {
          totalChannelData[i] = [[totalChannelData[i][0]]];
        }
      } else {
        // TODO:尚无多个单一孔数据
        for (let j = 0; j < onlyName.length; j++) {
          if (totalChannelData[i][0].length === 6 && totalChannelData[i][0][0].sampleName === onlyName[j]) {
            totalChannelData[i] = [[totalChannelData[i][0]]];
          }
        }
      }
    }
    let yArrayMean = [], aveSlop = [], arr2 = [], cloneStr = '';//字符串为空
    try {
      for (let m = 0; m < totalChannelData.length; m++) {//8组
        cloneSlopeCopy = [];
        for (let n = 0; n < totalChannelData[m][0].length; n++) {//每组2个，单独计算一组数据
          let test = totalChannelData[m][0].length;
          setSlope([]);
          var dataX, dataY;
          //选中的基准x数据
          let selectedIndex = map.get(totalChannelData[m][0][n][0].sampleName);
          // 基于x数据的索引
          let index = totalChannelData[m][0][n].findIndex(item => item.channelIndex === selectedIndex);
          dataX = totalChannelData[m][0][n][index]?.quantificationOrigin;
          // 未选中的待计算的y数据组
          dataY = totalChannelData[m][0][n].filter((item) => item.channelIndex !== selectedIndex);
          /*数据饱和预处理  (取最小值至最大值)
           最小值暂取0？？*/
          let min = dataX[0];
          let maxIndex = 0; //最大数值索引
          let minIndex = 0; //最小数值索引
          for (let i = 0; i < dataX.length; i++) {
            if (dataX[i] < min) {
              min = dataX[i];
              minIndex = i;
            }
          }
          // 最大值
          // let max = dataX[minIndex];//避免最大值在min的前面，从最小值以后开始遍历，初值设为最小值处
          // for (let i = 0; i < dataX.length; i++) {
          //   if (i > minIndex && dataX[i] > max) {
          //     max = dataX[i];
          //     maxIndex = i;
          //   }
          // }
          let max;
          for (let i = dataX.length - 1; i > 0;) {
            if (dataX[i] === dataX[i - 1]) {
              i--;
            } else {
              max = dataX[i];
              maxIndex = i;
              break;
            }
          }
          // console.log("最大值为：" + max + "位置为：" + maxIndex);
          // console.log("最小值为：" + min + "位置为：" + minIndex);
          dataX = dataX.slice(minIndex, maxIndex + 1);//不包含max + 1，保留一个最大值
          // console.log("dataX:",dataX);

          var xSum = 0;//x的多项和
          var ySum = 0;//y的多项和
          for (let i = 0; i < dataX?.length; i++) {
            xSum += dataX[i];//x的和
          }
          var xMean = xSum / dataX?.length;//x的平均数
          // console.log(xMean);
          //未选中的待计算k值的y数据之和的数组
          // console.log(dataY);
          for (let i = 0; i < dataY.length; i++) {
            for (let j = 0; j < dataX?.length; j++) {
              ySum += dataY[i].quantificationOrigin.slice(minIndex, maxIndex + 1)[j];
            }
            // console.log("第", i, "Y组数据:", dataY[i].quantificationOrigin);
            // yArray.push(ySum);//y的和
            yArrayMean.push(ySum / dataX?.length); //y的平均数
          }
          // console.log("yArray:", yArray, "yArrayMean:", yArrayMean);
          var num = 0;//多项式和【(x-x的均值)*(y-y的均值)】
          var den = 0;//多项式和【(x-x的均值)*(x-x的均值)】

          let molecule = [];
          //计算有问题？
          for (let j = 0; j < dataY.length; j++) {
            num = 0;
            for (let k = 0; k < dataX?.length; k++) {
              let y = dataY[j].quantificationOrigin.slice(minIndex, maxIndex + 1)[k];
              let x = dataX[k];
              num += (x - xMean) * (y - yArrayMean[j]);
            }
            molecule.push(num);
          }
          for (let i = 0; i < dataX?.length; i++) {
            let x = dataX[i];
            den += (x - xMean) * (x - xMean);
          }
          // console.log(den);
          for (let i = 0; i < dataY.length; i++) {
            let a = molecule[i] / den;   //y=ax+b的系数a  拟合直线的x系数
            //k值小于0d的统一为0，不存在0的情况
            if (a < 0 || a === 0) {
              a = 0.00000;
            }
            cloneSlopeCopy.push(a);
            // setSlope(cloneSlope);
          }
        }
        //该孔进行了n次此实验
        for (let j = 0; j < dataY.length; j++) {
          let number = 0;
          for (let i = j; i < cloneSlopeCopy.length; i = i + dataY.length) {//2*5次
            number = number + cloneSlopeCopy[i];
          }
          /*进行求well的相同sampleName的校准的均值*/
          //每个孔有数据通道的均值
          aveSlop.push((number / totalChannelData[m][0].length).toFixed(5));
        }
      }
      // console.log(aveSlop);//所有通道的均值
      let result = [], resultIndex = [], resultSampleName = [];

      for (let i = 0; i < totalChannelData[0][0][0].length; i++) {
        resultIndex.push(totalChannelData[0][0][0][i].channelIndex); //0134
      }
      for (let i = 0; i < totalChannelData.length; i++) {
        resultSampleName.push(totalChannelData[i][0][0][0].sampleName);
      }

      for (let i = 0; i < aveSlop.length; i += dataY.length) {
        result.push(aveSlop.slice(i, i + dataY.length));
      }
      //TODO:将对应的1，插入到指定位置,满孔可以，小于6个通道待定？
      console.log(result);
      console.log(totalChannelData);
      let number;
      for (let i = 0; i < result.length; i++) {
        if (result[i].length === 6) {
          number = map.get(totalChannelData[i][0][0][0].sampleName);
          result[i].splice(number, 0, 1);
        } else {
          let tempIndex = map.get(resultSampleName[i]);
          let insertIndex = resultIndex.findIndex(item => item === tempIndex);
          result[i].splice(insertIndex, 0, 1);
        }
      }
      //全部通道精校系数
      // console.log(result);
      //重新更新data.coefficients数组
      cloneCoefficientArr = deepClone([], cloneCoefficientArr);
      for (let i = 0; i < result.length; i++) {
        number = map.get(totalChannelData[i][0][0][0].sampleName);
        cloneCoefficientArr.push({'name': totalChannelData[i][0][0][0].sampleName, 'channel': number, 'coefficient': result[i]});
      }
      //cloneCoefficientArr去重
      arr2 = cloneCoefficientArr.filter((x, index, self) => {
        let arrids = [];
        cloneCoefficientArr.forEach((item, i) => {
          arrids.push(item.name);
        });
        return arrids.indexOf(x.name) === index;
      });
      // console.log(arr2);
      setCoefficientArr(arr2);
      dispatch(saveData({...data, coefficients: arr2}));
      // console.log(data);
      //定义输出对象，数组转为字符串
      for (let i = 0; i < arr2.length; i++) {
        cloneStr = cloneStr + `${arr2[i].name},${arr2[i].coefficient.toString()},\n`;
      }
      str.push(cloneStr);
      setStringChar(str);
      console.log(cloneStr);
      // let date = new Date();
      // let currentTime = date.toLocaleString('chinese', {hour12: false}).split(" ")[0];
    } catch (e) {
      console.log(e, totalChannelData, onlyName, "校准数据格式报错");
    }
  }, [isLoadDone]);

  //  拖动线改变Threshold
  const changeThreshold = useDebounce(value => {
    cloneData = deepClone(data, cloneData);
    let shouldRequest;
    if (isCq) {
      shouldRequest = cloneData.targets.some(item => {
        if (value && item.name === value.id && item.threshold !== value.dataList[0]) {
          item.threshold = value.dataList[0];
          cloneData.wells.forEach(well => well.targets.forEach(it => it.name === value.id && (it.threshold = value.dataList[0])));
          return true;
        } //  value是undefined或threshold没有改变时不用发送请求
      });
      shouldRequest = cloneData.plateSetting.targets.some(item => {
        if (value && item.name === value.id && item.threshold !== value.dataList[0]) {
          item.threshold = value.dataList[0];
          cloneData.wells.forEach(well => well.targets.forEach(it => it.name === value.id && (it.threshold = value.dataList[0])));
          return true;
        } //  value是undefined或threshold没有改变时不用发送请求
      });
    } else {
      shouldRequest = cloneData.targets.some(item => {
        if (value && item.name === value.id && Math.log10(item.threshold) !== value.dataList[0]) {
          item.threshold = Math.pow(10, value.dataList[0]);
          cloneData.wells.forEach(well => well.targets.forEach(it => it.name === value.id && (it.threshold = value.dataList[0])));
          return true;
        } //  value是undefined或threshold没有改变时不用发送请求
      });
      shouldRequest = cloneData.plateSetting.targets.some(item => {
        if (value && item.name === value.id && Math.log10(item.threshold) !== value.dataList[0]) {
          item.threshold = Math.pow(10, value.dataList[0]);
          cloneData.wells.forEach(well => well.targets.forEach(it => it.name === value.id && (it.threshold = value.dataList[0])));
          return true;
        } //  value是undefined或threshold没有改变时不用发送请求
      });
    }
    shouldRequest && request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(getAnalysisInfo(res.data).analysisShowLineArr));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }, 200);

  //  改变一个target的threshold
  function changeSingleTargetThreshold(targetName, value) {
    cloneData = deepClone(data, cloneData);
    cloneData.targets.some(item => item.name === targetName && (item.threshold = Number(value)));
    cloneData.plateSetting.targets.some(item => item.name === targetName && (item.threshold = Number(value)));
    cloneData.wells.forEach(item => item.targets.forEach(it => it.name === targetName && (it.threshold = Number(value))));
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(getAnalysisInfo(res.data).analysisShowLineArr));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  //  改变全部的target的threshold
  function changeAllThreshold(value) {
    cloneData = deepClone(data, cloneData);
    cloneData.targets.forEach(item => (item.threshold = Number(value)));
    cloneData.plateSetting.targets.forEach(item => (item.threshold = Number(value)));
    cloneData.wells.forEach(item => item.targets.forEach(it => it.threshold = Number(value)));
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(getAnalysisInfo(res.data).analysisShowLineArr));
            dispatch(saveAllThreshold(Number(value)));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  function omMouseDownListener(e) {
    if (e.buttons !== 1) {      //  判断鼠标左键按下
      return;
    }
    e.preventDefault();
    setStartX(e.clientX);
    setStartY(e.clientY);
    setLeftDown(true);
  }

  function omMouseMoveListener(e) {
    if (leftDown) {
      let offsetX = e.clientX - startX;
      let offsetY = e.clientY - startY;
      quantificationBox.current.scrollLeft = quantificationBox.current.scrollLeft - offsetX;
      // quantificationBox.current.scrollTop = quantificationBox.current.scrollTop - offsetY;
    }
  }

  //  Target Setting点击Opt操作
  function targetSettingSelect(indey) {
    cloneTarget = deepClone(target, cloneTarget);
    cloneTargetSelectedArr = deepClone(targetSelectedArr, cloneTargetSelectedArr);
    cloneTarget[indey].opt = !cloneTarget[indey].opt;
    cloneTargetSelectedArr = cloneTarget.filter(item => item.opt).map(item => item.name);
    setTarget(cloneTarget);
    dispatch(saveTargetSelectedArr(cloneTargetSelectedArr));
  }

  //  选择dataAnalysis方法
  function selectDataAnalysisMethod(value) {
    let method = "";
    switch (value) {
      case  DATA_ANALYSIS_METHOD_1:
        method = BASELINE_SUBTRACTED_CURVE_FIT;
        break;
      case DATA_ANALYSIS_METHOD_2:
        method = BASELINE_CORRECTION;
        break;
      case DATA_ANALYSIS_METHOD_3:
        method = RAW_DATA;
        break;
    }
    cloneData = deepClone(data, cloneData);
    cloneData.analysisMethodSetting.method = method;
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
    dispatch(saveDataAnalysisMethod(value));
  }

  //  改变Baseline,如果是Auto就自动将所有计算成3-15个循环
  function changeBaseLine(value) {
    dispatch(saveBaselineType(value));
    if (value === "default") {
      return;
    }
    cloneData = deepClone(data, cloneData);
    cloneAnalysisShowLineArr = deepClone(analysisShowLineArr, cloneAnalysisShowLineArr);
    cloneAnalysisShowLineArr.forEach(item => item.baseStartCycle.value = 3);
    cloneAnalysisShowLineArr.forEach(item => item.baseEndCycle.value = 15);
    cloneData.analysisMethodSetting.startCycle = 3;
    cloneData.analysisMethodSetting.endCycle = 15;
    cloneData.wells.forEach(well => well.lines.forEach(line => {
      line.baseStartCycle = 3;
      line.baseEndCycle = 15;
    }));
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(cloneAnalysisShowLineArr));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  //  改变AnalysisMethodSetting中的BaselineSetting
  function changeBaseLineAll(value, type) {
    let cloneBaseline = {...baseLine};
    cloneBaseline[type] = value;
    dispatch(saveBaseLine(cloneBaseline));
  }

  //  设置baseline,需要调用calCaAndSq
  function setBaseLineAll() {
    let startCycle = Number(baseLine.startCycle),
      endCycle = Number(baseLine.endCycle);
    if (startCycle > endCycle) {
      return message.warn("Start cycle can not more than end Cycle.");
    }
    cloneData = deepClone(data, cloneData);
    cloneAnalysisShowLineArr = deepClone(analysisShowLineArr, cloneAnalysisShowLineArr);
    cloneAnalysisShowLineArr.forEach(item => item.baseStartCycle.value = Number(startCycle));
    cloneAnalysisShowLineArr.forEach(item => item.baseEndCycle.value = Number(endCycle));
    cloneData.analysisMethodSetting.startCycle = Number(startCycle);
    cloneData.analysisMethodSetting.endCycle = Number(endCycle);
    cloneData.wells.forEach(well => well.lines.forEach(line => {
      line.baseStartCycle = Number(startCycle);
      line.baseEndCycle = Number(endCycle);
    }));
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(cloneAnalysisShowLineArr));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  //  改变AnalysisMethodSetting中的Mode
  function changeDefaultMethodSettingMode(value) {
    cloneData = deepClone(data, cloneData);
    cloneData.analysisMethodSetting.mode = value;
    if (value === THRESHOLD) {
      dispatch(saveCqSingleThreshold(THRESHOLD));
    } else if (value === CUSTOM_THRESHOLD) {
      dispatch(saveCqSingleThreshold(CUSTOM_THRESHOLD));
    } else if (value === SINGLE_THRESHOLD) {
      cloneData.analysisMethodSetting.mode = cqSingleThreshold;
      setSingleThreshold(true);
    }
    if (value === CQMAN || value === REGRESSION || value === EXTREMUM) {
      setSingleThreshold(false);
    }
    request({
      url: 'analysis/calAll',
      data: {...cloneData},
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            dispatch(saveData(res.data));
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  //  重新分析实验
  function analysisExperiment() {
    request({
      url: 'analysis/calAll',
      data: data,
      method: 'post'
    })
      .then(res => {
        switch (res.code) {
          case 200:
            //  保存data
            calCqMean(res.data);
            calQuantityMean(res.data);
            dispatch(saveData(res.data));
            dispatch(saveAnalysisShowLineArr(getAnalysisInfo(res.data).analysisShowLineArr)); //  保存可以画线的数据(只有target和sample同时选择后才能画线)
            saveEndPointSetting(res.data);
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      })
      .catch(err => message.error(err));
  }

  //去除一个数组a在另一个数组b里的全部元素
  function arrChange(a, b) {
    for (let i = 0; i < b.length; i++) {
      for (let j = 0; j < a.length; j++) {
        if (a[j] === b[i]) {//如果是id相同的，那么a[ j ].id == b[ i ].id
          a.splice(j, 1);
          j = j - 1;
        }
      }
    }
    return a;
  }

  /*
   最小二乘法求解拟合的k值，公式待定？，相同sampleName孔处理
   Y=kX+b
   k=[Sum累加（Yi-Ymean）(Xi-Xmean)]/[Sum累加(Xi-Xmean)^2]
   */
  function linearRegression() {
    cloneChannelArr = deepClone(channelArr, cloneChannelArr);
    console.log(cloneChannelArr);
    cloneSlope = deepClone([], cloneSlope);
    setChannelLines(channels.leastChannelLines);
    cloneChannelLines = deepClone(channelLines, cloneChannelLines);
    //数组预处理，把每组well选中的数据存成一个新的对象数组
    let dataArrayLength = cloneChannelLines.length / 6;
    channelLinesDataArray.length = dataArrayLength;
    let origin = [];
    for (let j = 0; j < dataArrayLength; j++) {
      origin = [];
      for (let k = j * 6; k < j * 6 + 6; k++) {
        origin = [...origin, ...[cloneChannelLines[k]]];
      }
      channelLinesDataArray[j] = origin;  //选中well的origin数据对象数组
    }
    for (let i = 0; i < channelLinesDataArray.length; i++) {
      for (let j = 0; j < channelLinesDataArray[0].length; j++) {
        //往对象里添加channel属性
        let key = "channel", key1 = "opt";
        channelLinesDataArray[i][j][key] = cloneChannelArr[j].channel;
        channelLinesDataArray[i][j][key1] = cloneChannelArr[j].opt;
      }
    }
    let yArrayMean = [], aveSlop = [];
    try {
      for (let m = 0; m < channelLinesDataArray.length; m++) {
        let dataX, dataY;
        //选中的基准x数据
        dataX = channelLinesDataArray[m].filter((item) => item.opt && item.quantificationOrigin)[0]?.quantificationOrigin;
        // 未选中的待计算的y数据组
        dataY = channelLinesDataArray[m].filter((item) => !item.opt && item.channel !== '-' && item.quantificationOrigin);
        //数据饱和预处理  (取最小值至最大值)
        // 最小值暂取0？？
        let min = dataX[0];
        let maxIndex = 0; //最大数值索引
        let minIndex = 0; //最小数值索引
        for (let i = 0; i < dataX.length; i++) {
          if (dataX[i] < min) {
            min = dataX[i];
            minIndex = i;
          }
        }
        // 最大值 TODO:最大值判定
        // let max = dataX[minIndex];//避免最大值在min的前面，从最小值以后开始遍历，初值设为最小值处
        // for (let i = 0; i < dataX.length; i++) {
        //   if (i > minIndex && dataX[i] > max) {
        //     max = dataX[i];
        //     maxIndex = i;
        //   }
        // }
        let max;
        for (let i = dataX.length - 1; i > 0;) {
          if (dataX[i] === dataX[i - 1]) {
            i--;
          } else {
            max = dataX[i];
            maxIndex = i;
            break;
          }
        }
        // console.log("最大值为：" + max + "位置为：" + maxIndex);
        // console.log("最小值为：" + min + "位置为：" + minIndex);
        dataX = dataX.slice(minIndex, maxIndex + 1);//不包含max + 1，保留一个最大值
        // console.log("dataX",dataX);
        // console.log(dataY);
        var xSum = 0, ySum = 0;//x、y的多项和
        for (let i = 0; i < dataX?.length; i++) {
          xSum += dataX[i];//x的和
        }
        var xMean = xSum / dataX?.length;//x的平均数
        // console.log(xMean);
        // console.log(dataY);

        // 未选中的待计算k值的y数据之和的数组
        for (let i = 0; i < dataY.length; i++) {
          for (let j = 0; j < dataX?.length; j++) {
            ySum += dataY[i].quantificationOrigin.slice(minIndex, maxIndex + 1)[j];
          }
          // console.log("第", i, "Y组数据:", dataY[i].quantificationOrigin);
          // yArray.push(ySum);//y的和
          yArrayMean.push(ySum / dataX?.length); //y的平均数
        }
        // console.log("yArrayMean:", yArrayMean);
        var num = 0;    //多项式和【(x-x的均值)*(y-y的均值)】
        var den = 0;    //多项式和【(x-x的均值)*(x-x的均值)】
        let molecule = [];    //计算有问题？
        for (let j = 0; j < dataY.length; j++) {
          num = 0;
          for (let k = 0; k < dataX?.length; k++) {
            let y = dataY[j].quantificationOrigin.slice(minIndex, maxIndex + 1)[k];
            let x = dataX[k];
            num += (x - xMean) * (y - yArrayMean[j]);
          }
          molecule.push(num);
        }
        for (let i = 0; i < dataX?.length; i++) {
          let x = dataX[i];
          den += (x - xMean) * (x - xMean);
        }
        // console.log(den);
        for (let i = 0; i < dataY.length; i++) {
          let a = molecule[i] / den;   //y=ax+b的系数a  拟合直线的x系数
          //k值小于0d的统一为0，不存在0的情况
          if (a < 0 || a === 0) {
            a = 0.00000;
          }
          cloneSlope.push(a);
          setSlope(cloneSlope);
        }
        // console.log(cloneSlope);
        setChannelArr(cloneChannelArr);
        // dispatch(saveChannel(cloneChannelArr));
      }
    } catch (e) {
      console.log(e);
    }
    cloneChannelArr.forEach(item => item.opt && item.confficients === 1);
    var arr = cloneChannelArr.filter(item => item.channel !== '-' && !item.opt);
    /*进行求well的相同sampleName的校准的均值*/
    try {
      let slopeLength = cloneSlope.length / channelLinesDataArray.length;
      for (let i = 0; i < slopeLength; i++) {
        let number = 0;
        for (let j = i; j < cloneSlope.length; j = j + slopeLength) {
          number = number + cloneSlope[j];
        }
        aveSlop.push(number / channelLinesDataArray.length);
        arr[i].confficients = aveSlop[i].toFixed(5);
        // console.log(aveSlop[i]);//每个同类孔的精校
      }
      // console.log(aveSlop);
    } catch (e) {
      console.log(e);
    }
    // console.log(cloneChannelArr);
    cloneChannelArr.forEach(item => {
      if (item.name === '-') {
        item.confficients = 0;
      } else if (item.opt) {
        item.confficients = 1;
      }
    });
    // let selectedChannelArr=cloneChannelArr.filter(item=> item.confficients);
    let selectedChannelArr = [];
    for (let i = 0; i < cloneChannelArr.length; i++) {
      // console.log(cloneChannelArr[i].confficients);
      selectedChannelArr.push(Number(cloneChannelArr[i].confficients));
    }
    // dispatch(saveChannel({...channel,wellArr:cloneChannelArr}))
    //获得选中的Channel值
    let selectedName = cloneChannelArr.filter(item => item.opt)[0]?.name;
    let selectedChannel = cloneChannelArr.filter(item => item.opt)[0]?.channelIndex;
    cloneCoefficientArr = deepClone(coefficientArr, cloneCoefficientArr);
    // console.log(cloneCoefficientArr);
    if (cloneCoefficientArr.length === 0) {  //重新计算不应覆盖原有data的系数，已在最开始导入cqa时计算存储完毕
      //重新更新data.coefficients数组
      cloneCoefficientArr.push({'name': selectedName, 'channel': selectedChannel, 'coefficient': selectedChannelArr});
      //cloneCoefficientArr去重
      let arr2 = cloneCoefficientArr.filter((x, index, self) => {
        let arrids = [];
        cloneCoefficientArr.forEach((item, i) => {
          arrids.push(item.name);
        });
        return arrids.indexOf(x.name) === index;
      });
      dispatch(saveChannel({...channel, coefficientArr: arr2}));
      setCoefficientArr(arr2);//更新精校数组
    }
    channels.wellArr = cloneChannelArr;
    setChannel(channels.wellArr);
    setChannelArr(cloneChannelArr);
  }

  function changeOpt(bool, index) {
    setClick(!click);
    //未选中的状态下count都为0
    cloneChannelArr = deepClone(channelArr, cloneChannelArr);
    console.log(cloneChannelArr);
    if (count < 1) {
      cloneChannelArr[index].opt = !cloneChannelArr[index].opt;
      if (bool) {
        cloneChannelArr[index].opt = !cloneChannelArr[index].opt;
      }
      setCount(1);
      setChannelArr(cloneChannelArr);
    }
    if (bool) {
      cloneChannelArr[index].opt = !cloneChannelArr[index].opt;
      setCount(0);
      setChannelArr(cloneChannelArr);
    }
    if (count === 1 && !bool) {
      cloneChannelArr[index].opt = !cloneChannelArr[index].opt;
      setChannelArr(cloneChannelArr);
    }
    let optArr = cloneChannelArr.filter(item => item.opt);
    if (optArr.length > 1) {
      setCount(1);
      return message.warn("Please choose one channel!  " +
        "If the first choice is error,try to select wells again!");
    }
    // cloneChannelArr[index].opt && linearRegression();
    // let buttonCalculate = document.getElementById('calculi');
    // buttonCalculate.click();
    // console.log(cloneChannelArr);
  }

  //保存精校数据
  function savelConfficent() {
    cloneChannelArr = deepClone(channelArr, cloneChannelArr);
    cloneCoefficientArr = deepClone(coefficientArr, cloneCoefficientArr);
    setChannelArr(cloneChannelArr);
    dispatch(saveData({...data, coefficients: cloneCoefficientArr}));
    console.log(data);
  }

  //input改校准系数并保存数据结构里
  function changeCoefficient(value, channelIndex, name) {
    cloneCoefficientArr = deepClone(coefficientArr, cloneCoefficientArr);
    cloneChannelArr = deepClone(channelArr, cloneChannelArr);
    let coeffiIndex = cloneChannelArr.findIndex(item => item.name === name);
    cloneChannelArr[coeffiIndex].confficients = Number(value);
    channels.wellArr = cloneChannelArr;
    setChannel(channels.wellArr);
    setChannelArr(cloneChannelArr);
    //将修改后的channel里的校准系数作为一个新数组存到data大数据结构里对应的name/channel单个索引里
    // console.log(channels);
    let tempArray = [], tempName;
    for (let i = 0; i < channels.wellArr.length; i++) {
      tempArray.push(channels.wellArr[i].confficients);
      if (channels.wellArr[i].confficients === 1) {
        tempName = channels.wellArr[i].channel;
      }
    }
    //传给data=>coefficents
    for (let i = 0; i < data.coefficients.length; i++) {
      if (data.coefficients[i].name === tempName) {
        data.coefficients[i].coefficient = tempArray;
        // dispatch(saveData({...data, coefficients: tempArray}));
        setBigDataCalibration(data.coefficients[i].coefficient);
      }
    }
    //更新导出的文档字符串？存在bug:切换页面字符串消失清空，可能需要redux存储管理？
    let str = [];
    let cloneStr = '';//字符串为空
    //定义输出对象，数组转为字符串
    for (let i = 0; i < data.coefficients.length; i++) {
      cloneStr = cloneStr + `${data.coefficients[i].name},${data.coefficients[i].coefficient.toString()},\n`;
    }
    str.push(cloneStr);
    setStringChar(str);
    /* 获得opt为true时的索引
     for (let i = 0; i < cloneChannelArr.length; i++) {
     if (cloneChannelArr[i].opt) {
     index = cloneChannelArr[i].channelIndex;} }
     //待解决每次只能存一个修改值
     for (let i = 0; i < cloneCoefficientArr.length; i++) {
     if (cloneCoefficientArr[i].channel === index) {
     for (let j = 0; j < cloneCoefficientArr[i].coefficient.length; j++) {
     if (j === channelIndex) {
     cloneCoefficientArr[i].coefficient[j] = Number(value); }}} }
     console.log(cloneCoefficientArr);
     dispatch(saveData({...data, coefficients: cloneCoefficientArr}));
     setBigDataCalibration(cloneCoefficientArr);*/
    // console.log(data);
    console.log("修改后的校准", cloneStr);
    analysisExperiment();
  }

  //低维数组按某一属性归类成高维数组
  function groupBy(array, f) {
    let groups = {};
    array.forEach(function (o) {
      let group = JSON.stringify(f(o));
      groups[group] = groups[group] || [];
      groups[group].push(o);
    });
    return Object.keys(groups).map(function (group) {
      return groups[group];
    });
  }

  //下载方法
  function download(filename, content, contentType) {
    if (!contentType) {
      contentType = 'application/octet-stream';
    }
    let a = document.createElement('a');
    let blob = new Blob([content], {'type': contentType});
    a.href = window.URL.createObjectURL(blob);
    a.download = filename;
    a.click();
  }

  function saveTxt() {
    let cloneStringChar;
    cloneStringChar = deepClone(stringChar, cloneStringChar);
    console.log(cloneStringChar);
    download(data.experimentName, cloneStringChar[0], "");
  }

  return showLargeQuantificationPic
    ? <div className="largeQuantificationBox"
           onDoubleClick={() => setShowLargeQuantificationPic(false)}
           id="largeQuantification"
    />
    : <div className="analysisQuantification">
      <section className="analysisQuantificationTops">
        <div className="analysisQuantificationTopLeft">
          <div>
            <div>{isCN ? "计算" : "Calibration"}</div>
            <ul>
              <li style={isCq ? {backgroundColor: "#213040", color: "#fff"} : null}
                  onClick={() => setIsCq(true)}
              >Cq
              </li>
              <li style={!isCq ? {backgroundColor: "#213040", color: "#fff"} : null}
                  onClick={() => setIsCq(false)}
              >Log
              </li>
            </ul>
          </div>
          {
            isCq
              ? <div ref={quantificationBox}
                     style={{overflow: "auto"}}
                     className="scrollBarStyle quantificationCanvasBox"
                     onMouseDown={omMouseDownListener}
                     onMouseMove={omMouseMoveListener}
                     onMouseUp={() => setLeftDown(false)}
              >
                <section id="quantification"/>
              </div>
              : <div ref={quantificationBox}
                     style={{overflow: "auto"}}
                     className="scrollBarStyle quantificationCanvasBox"
                     onMouseDown={omMouseDownListener}
                     onMouseMove={omMouseMoveListener}
                     onMouseUp={() => setLeftDown(false)}
              >
                <section id="quantification"/>
              </div>
          }
          <div>
            <div onClick={() => setAutoAxes(!autoAxes)}
                 className={autoAxes ? "selectedStyle" : null}/>
            {
              autoAxes
                ? <div style={{width: 100}}>{isCN ? "自动Y轴" : "Auto Axes"}</div>
                // : <div>
                : <div style={{fontSize: isCN ? '15px' : "16px"}}>
                  <label htmlFor="Min" style={{marginLeft: 10}}> {isCN ? "最小值" : "Min"}
                    <input id="Min" type="number"
                           value={minY}
                           onChange={e => setMinY(e.target.value)}
                    />
                  </label>
                  <label htmlFor="Max"> {isCN ? "最大值" : "Max"}
                    <input id="Max" type="number"
                           value={maxY}
                           onChange={e => setMaxY(e.target.value)}
                    />
                  </label>
                </div>
            }
          </div>
          <div className="quantificationLargeBtn"
               onClick={() => setShowLargeQuantificationPic(true)}
          />
        </div>
        {
          <div className="analysisQuantificationTopRight">
            <div className="standardCanvasBox">
              <Title imgClassPic="saveCoefficens" imgActionSave={saveTxt} name="Calibration"/>
              <ul>
                <li>Source</li>
                <li>Channel</li>
                <li>Target</li>
                <li>Coefficients</li>
              </ul>
              <section>
                {
                  channelArr?.map((item, index) => (
                    <ul key={index + item.name + item.channel}>
                      <li onClick={() => changeOpt(item.opt, index)}
                          className={item.opt ? "selectedStyleOpt" : "selectOpt"}
                          style={{cursor: "pointer"}}>
                      </li>
                      <li>{`channel${index + 1}`}</li>
                      <li>
                        <div key={item.channel}>{item.channel}</div>
                      </li>
                      <li>
                        <input type="text"
                               key={item.opt + item.name + item.confficients + item.channel + item.channelIndex}
                               defaultValue={item.opt ? '1' : item.channel !== '-' && !item.opt ? item.confficients : "-"}
                               onBlur={e => changeCoefficient(e.target.value, item.channelIndex, item.name)}
                        />
                      </li>
                    </ul>
                  ))
                }
              </section>
              <div className="calculateStyle">
                {/*<li onClick={savelConfficent}>Save</li>*/}
                <li id="calculi" onClick={linearRegression}>Calculate</li>
                {/*<li onClick={clear}>Clear</li>*/}
              </div>
            </div>
            {/*<LineRegression option={lineOption}*/}
            {/*/>*/}
          </div>
        }
      </section>
      <section className="analysisQuantificationBottom">
        <CalculateTable plateClass="runPagePlateTableSmall"
                        lineId={lineId}
                        setWellId={setWellId}
        />
        <div>
          <div className="analysisQuantificationTargetSetting">
            <Title name={isCN ? "目标基因设置" : "Target Setting"}/>
            <ul>
              <li>{isCN ? "选择" : "Opt"}</li>
              <li>{isCN ? "基因" : "Target"}</li>
              <li>{isCN ? "颜色" : "Color"}</li>
              <li>{isCN ? "通道" : "Channel"}</li>
              <li>{isCN ? "阈值" : "Threshold"}</li>
            </ul>
            <section className="scrollBarStyle">
              {
                target.map((item, index) => (
                  <ul key={item.name + item.threshold}>
                    <li onClick={() => targetSettingSelect(index)}
                        className={item.opt ? "selectedStyle" : ""}
                        style={{cursor: "pointer"}}
                    />
                    <li>{item.name}</li>
                    <li>
                      <div style={{backgroundColor: `${item.color}`}}/>
                    </li>
                    <li>{item.channel}</li>
                    <input key={item.threshold}
                           readOnly={data.analysisMethodSetting.mode !== CUSTOM_THRESHOLD}
                           defaultValue={isNaN(Number(item.threshold)) ? -1 : Number(item.threshold).toFixed(3)}
                           onBlur={e => changeSingleTargetThreshold(item.name, e.target.value)}
                    />
                  </ul>
                ))
              }
            </section>
          </div>
          <div onClick={() => setShowMethodSetting(true)}>{isCN ? "默认设置" : "Default Method Setting"}</div>
          {
            showMethodSetting
              ? <div className="methodSetting asideBoxHeader" style={{zIndex: 1}}>
                <header>
                  <div>
                    <p>{isCN ? "分析参数设置" : "Analysis Method Setting"}</p>
                    <p onClick={() => setShowMethodSetting(false)}/>
                  </div>
                  <hr/>
                </header>
                <ul>
                  <li>
                    <div>{isCN ? "扩增曲线算法" : "Data Analysis Method"}</div>
                    <Dropdown
                      overlay={
                        <Menu>
                          {
                            dataAnalysisMethods.map(item => (
                              <Menu.Item key={item}>
                                <div style={{...MENU_STYLE, width: 510}}
                                     onClick={() => selectDataAnalysisMethod(item)}
                                >{item}</div>
                              </Menu.Item>
                            ))
                          }
                        </Menu>
                      }
                      overlayClassName="antdDropDownStyle"
                      placement="bottomCenter"
                      trigger={['click']}
                    >
                      <div style={{cursor: "pointer"}}>{dataAnalysisMethod}</div>
                    </Dropdown>
                  </li>
                  <li>
                    <div>{isCN ? "Cq值算法" : "Cq Determination Mode"}</div>
                    <div>
                      <label htmlFor="SingleThreshold">
                        <input type="radio" value={SINGLE_THRESHOLD} name="CqMode" id="SingleThreshold"
                               defaultChecked={data.analysisMethodSetting.mode === THRESHOLD || data.analysisMethodSetting.mode === CUSTOM_THRESHOLD}
                               onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                        /> {isCN ? "单一阈值法" : "Single Threshold"}
                      </label>
                      <label htmlFor="CqMan">
                        <input type="radio" value={CQMAN} name="CqMode" id="CqMan"
                               defaultChecked={data.analysisMethodSetting.mode === CQMAN}
                               onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                        /> {isCN ? "CqMan法" : "CqMan"}
                      </label>
                      <label htmlFor="Regression">
                        <input type="radio" value={REGRESSION} name="CqMode" id="Regression"
                               defaultChecked={data.analysisMethodSetting.mode === REGRESSION}
                               onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                        /> {isCN ? "回归法" : "Regression"}
                      </label>
                      <label htmlFor="Extremum">
                        <input type="radio" value={EXTREMUM} name="CqMode" id="Extremum"
                               defaultChecked={data.analysisMethodSetting.mode === EXTREMUM}
                               onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                        /> {isCN ? "极值法" : "Extremum"}
                      </label>
                    </div>
                  </li>
                  {
                    singleThreshold
                      ? <li>
                        <div>{isCN ? "阈值设置" : "Cq Single Threshold"}</div>
                        <div>
                          <label htmlFor="CqThresholdAuto">
                            <input type="radio" value={THRESHOLD} name="Single" id="CqThresholdAuto"
                                   checked={data.analysisMethodSetting.mode === THRESHOLD}
                                   onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                            /> {isCN ? "自动" : "Auto"}
                          </label>
                          <label htmlFor="CqThresholdDefault">
                            <input type="radio" value={CUSTOM_THRESHOLD} name="Single" id="CqThresholdDefault"
                                   checked={data.analysisMethodSetting.mode === CUSTOM_THRESHOLD}
                                   onChange={e => changeDefaultMethodSettingMode(e.target.value)}
                            /> {isCN ? "手动" : "Set Default"}
                          </label>
                          <label htmlFor="CqThreshold">
                            {isCN ? "阈值" : "Threshold"} <input type="number" id="CqThreshold"
                                                               readOnly={data.analysisMethodSetting.mode !== CUSTOM_THRESHOLD}
                                                               defaultValue={allThreshold}
                                                               onBlur={e => changeAllThreshold(e.target.value)}
                          />
                          </label>
                        </div>
                      </li>
                      : null
                  }
                  {
                    singleThreshold
                      ? <li>
                        <div>{isCN ? "基线设置" : "Baseline Setting"}</div>
                        <div>
                          <label htmlFor="BaselineSettingAuto">
                            <input type="radio" name="BaseLineSetting" id="BaselineSettingAuto"
                                   value={"auto"}
                                   defaultChecked={baselineType === "auto"}
                                   onChange={e => changeBaseLine(e.target.value)}
                            /> {isCN ? "自动" : "Auto"}
                          </label>
                          <label htmlFor="BaselineSettingDefault">
                            <input type="radio" name="BaseLineSetting" id="BaselineSettingDefault"
                                   value={"default"}
                                   defaultChecked={baselineType === "default"}
                                   onChange={e => changeBaseLine(e.target.value)}
                            /> {isCN ? "手动" : "Set Default"}
                          </label>
                          <span>
                        <input type="number"
                               value={baseLine.startCycle}
                               readOnly={baselineType === "auto"}
                               onChange={e => changeBaseLineAll(e.target.value, "startCycle")}
                        />
                      </span>
                          <span>to</span>
                          <span>
                        <input type="number"
                               value={baseLine.endCycle}
                               readOnly={baselineType === "auto"}
                               onChange={e => changeBaseLineAll(e.target.value, "endCycle")}
                        />
                      </span>
                          <span className="baselineSettingOk" onClick={setBaseLineAll}>{isCN ? "确定" : "OK"}</span>
                        </div>
                      </li>
                      : null
                  }
                </ul>
              </div>
              : null
          }
        </div>
        <div style={{position: "relative"}}>
          {/*<div ref={messageTable} className="tableStyle scrollBarStyle" style={{overflow: "auto"}}>*/}
          {/*  <ul style={{zIndex: 0}}>*/}
          {/*  </ul>*/}
          {/*</div>*/}
        </div>
      </section>
    </div>
    ;
})
;